Sensor Fusion for Kinetis MCUs (ISSDK/KSDK version)
debug.c
Go to the documentation of this file.
1 // Copyright (c) 2014, 2015, 2016, NXP Semiconductors N.V.,
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name of NXP Semiconductors N.V. nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 // DISCLAIMED. IN NO EVENT SHALL NXP SEMICONDUCTORS N.V. BE LIABLE FOR ANY
19 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 /*! \file debug.c
27  \brief ApplyPerturbation function used to analyze dynamic performance
28 
29  The ApplyPerturbation function applies a user-specified step function to
30  prior fusion results which is then "released" in the next fusion cycle.
31  When used in conjustion with the NXP Sensor Fusion Toolbox, this provides
32  a visual indication of the dynamic behavior of the library.
33 
34  Also included is some code for white-box testing within the IAR debug
35  environment. It can be used to evaluate propagation delays for tilt and
36  eCompass algorithms. It makes no sense with regard to "Rotation", because
37  that algorithm is simple gyro integration, and will never return to the
38  starting point. It will also overestimate delays for the kalman filters,
39  as there is no actual gyro data corresponding to the simulated step function.
40  So those filters are not operating as they would in the normal world.
41 */
42 
43 #include "sensor_fusion.h"
44 #include "control.h"
45 #include "stdlib.h"
46 #include "build.h"
47 
48 /// The ApplyPerturbation function applies a user-specified step function to
49 /// prior fusion results which is then "released" in the next fusion cycle.
50 /// When used in conjustion with the NXP Sensor Fusion Toolbox, this provides
51 /// a visual indication of the dynamic behavior of the library.
52 /// This function is normally involved via the "sfg." global pointer.
54 {
55 #ifdef INCLUDE_DEBUG_FUNCTIONS
56  // volatile keyword used to force compiler not to optimize out these
57  // variables. this does unfortunately result in a couple of warnings (which
58  // can be ignored) farther down in this code.
59  volatile static uint16_t iTestProgress; ///< Perturbation test status
60  volatile static uint16_t iTestDelay = 0; ///< Measured delay
61  volatile static uint16_t iTestAngle = 0; ///< Integer Residual angle associated with measured delay
62  volatile float angle=0.0f; ///< Float Residual angle associated with measured delay
63  volatile static float threshold=0;
64  static Quaternion StartingQ = {
65  .q0 = 1.0,
66  .q1 = 0.0,
67  .q2 = 0.0,
68  .q3 = 0.0
69  };
70  Quaternion CurrentQ = {
71  .q0 = 1.0,
72  .q1 = 0.0,
73  .q2 = 0.0,
74  .q3 = 0.0
75  };
76  // cache local copies of control flags so we don't have to keep dereferencing pointers below
77  quaternion_type quaternionPacketType;
78  quaternionPacketType = sfg->pControlSubsystem->QuaternionPacketType;
79 
80  Quaternion ftmpq; // scratch quaternion
81 
82  // calculate the test perturbation
83  switch (sfg->iPerturbation)
84  {
85  case 1: // 180 degrees about X
86  ftmpq.q0 = 0.0F;
87  ftmpq.q1 = 1.0F;
88  ftmpq.q2 = 0.0F;
89  ftmpq.q3 = 0.0F;
90  threshold = 90.0;
91  break;
92 
93  case 2: // 180 degrees about Y
94  ftmpq.q0 = 0.0F;
95  ftmpq.q1 = 0.0F;
96  ftmpq.q2 = 1.0F;
97  ftmpq.q3 = 0.0F;
98  threshold = 90.0;
99  break;
100 
101  case 3: // 180 degrees about Z
102  ftmpq.q0 = 0.0F;
103  ftmpq.q1 = 0.0F;
104  ftmpq.q2 = 0.0F;
105  ftmpq.q3 = 1.0F;
106  threshold = 90.0;
107  break;
108 
109  case 4: // -90 degrees about X
110  ftmpq.q0 = ONEOVERSQRT2;
111  ftmpq.q1 = -ONEOVERSQRT2;
112  ftmpq.q2 = 0.0F;
113  ftmpq.q3 = 0.0F;
114  threshold = 45.0;
115  break;
116 
117  case 5: // +90 degrees about X
118  ftmpq.q0 = ONEOVERSQRT2;
119  ftmpq.q1 = ONEOVERSQRT2;
120  ftmpq.q2 = 0.0F;
121  ftmpq.q3 = 0.0F;
122  threshold = 45.0;
123  break;
124 
125  case 6: // -90 degrees about Y
126  ftmpq.q0 = ONEOVERSQRT2;
127  ftmpq.q1 = 0.0F;
128  ftmpq.q2 = -ONEOVERSQRT2;
129  ftmpq.q3 = 0.0F;
130  threshold = 45.0;
131  break;
132 
133  case 7: // +90 degrees about Y
134  ftmpq.q0 = ONEOVERSQRT2;
135  ftmpq.q1 = 0.0F;
136  ftmpq.q2 = ONEOVERSQRT2;
137  ftmpq.q3 = 0.0F;
138  threshold = 45.0;
139  break;
140 
141  case 8: // -90 degrees about Z
142  ftmpq.q0 = ONEOVERSQRT2;
143  ftmpq.q1 = 0.0F;
144  ftmpq.q2 = 0.0F;
145  ftmpq.q3 = -ONEOVERSQRT2;
146  threshold = 45.0;
147  break;
148 
149  case 9: // +90 degrees about Z
150  ftmpq.q0 = ONEOVERSQRT2;
151  ftmpq.q1 = 0.0F;
152  ftmpq.q2 = 0.0F;
153  ftmpq.q3 = ONEOVERSQRT2;
154  threshold = 45.0;
155  break;
156 
157  default: // No rotation
158  ftmpq.q0 = 1.0F;
159  ftmpq.q1 = 0.0F;
160  ftmpq.q2 = 0.0F;
161  ftmpq.q3 = 0.0F;
162  break;
163  }
164 
165  switch (quaternionPacketType) {
166 #if F_3DOF_G_BASIC
167  case (Q3):
168  CurrentQ = sfg->SV_3DOF_G_BASIC.fLPq;
169  qAeqAxB(&(sfg->SV_3DOF_G_BASIC.fLPq), &ftmpq);
170  break;
171 #endif
172 #if F_3DOF_B_BASIC
173  case (Q3M):
174  CurrentQ = sfg->SV_3DOF_B_BASIC.fLPq;
175  qAeqAxB(&(sfg->SV_3DOF_B_BASIC.fLPq), &ftmpq);
176  break;
177 #endif
178 #if F_3DOF_Y_BASIC
179  case (Q3G):
180  CurrentQ = sfg->SV_3DOF_Y_BASIC.fq;
181  qAeqAxB(&(sfg->SV_3DOF_Y_BASIC.fq), &ftmpq);
182  break;
183 #endif
184 #if F_6DOF_GB_BASIC
185  case (Q6MA):
186  CurrentQ = sfg->SV_6DOF_GB_BASIC.fLPq;
187  qAeqAxB(&(sfg->SV_6DOF_GB_BASIC.fLPq), &ftmpq);
188  break;
189 #endif
190 #if F_6DOF_GY_KALMAN
191  case (Q6AG):
192  CurrentQ = sfg->SV_6DOF_GY_KALMAN.fqPl;
193  qAeqAxB(&(sfg->SV_6DOF_GY_KALMAN.fqPl), &ftmpq);
194  break;
195 #endif
196 #if F_9DOF_GBY_KALMAN
197  case (Q9):
198  CurrentQ = sfg->SV_9DOF_GBY_KALMAN.fqPl;
199  qAeqAxB(&(sfg->SV_9DOF_GBY_KALMAN.fqPl), &ftmpq);
200  break;
201 #endif
202  default:
203  CurrentQ.q0 = 1.0;
204  CurrentQ.q1 = 0.0;
205  CurrentQ.q2 = 0.0;
206  CurrentQ.q3 = 0.0;
207  break;
208  }
209 
210  // Begin of code for white-box testing - requires IAR debugger
211  switch (iTestProgress) {
212  case 0: // no test in progress, check to see if we should start one
213  if (sfg->iPerturbation>0) {
214  // Start Test
215  iTestProgress = 1;
216  sfg->iPerturbation = 0;
217  iTestDelay = 0;
218  iTestAngle = 0;
219  // We'll need the complex conjugate of the starting quaternion
220  StartingQ.q0 = CurrentQ.q0;
221  StartingQ.q1 = -1 * CurrentQ.q1;
222  StartingQ.q2 = -1 * CurrentQ.q2;
223  StartingQ.q3 = -1 * CurrentQ.q3;
224  }
225  break;
226  default: // Test in progress, check to see if trigger reached
227  iTestDelay += 1;
228  qAeqAxB(&CurrentQ, &StartingQ);
229  angle = 2 * F180OVERPI * acos(CurrentQ.q0);
230  angle = fmod(fabs(angle), 180.0);
231  iTestAngle = (uint16_t) (10 * angle);
232  // In IAR, you can use a Log breakpoint to monitor "return to stationary pose".
233  // Use the following expression in the Message field and check the
234  // checkbox for C-Spy macro. Then Click any of the "Test" buttons
235  // in the Sensor Fusion Toolbox and monitor the results in the Messages window.
236  //"Delay=", iTestDelay:%d, " Angle=",iTestAngle:%d
237  if (angle<threshold) iTestProgress=2; // triggered
238  if (angle < (0.2 * threshold)) iTestProgress=0; // test is done
239  if (iTestDelay>100) iTestProgress=0; // abort test
240  break;
241  }
242  // End of code for white-box testing
243 #endif
244 }
enum quaternion quaternion_type
the quaternion type to be transmitted
Quaternion derived from full 9-axis sensor fusion.
Definition: sensor_fusion.h:70
#define ONEOVERSQRT2
1/sqrt(2)
float q0
scalar component
Definition: orientation.h:39
Quaternion derived from 3-axis mag only (auto compass algorithm)
Definition: sensor_fusion.h:66
The top level fusion structure.
float q3
z vector component
Definition: orientation.h:42
Quaternion derived from 3-axis gyro only (rotation)
Definition: sensor_fusion.h:67
Quaternion derived from 3-axis accel + 3 axis mag (eCompass)
Definition: sensor_fusion.h:68
Quaternion derived from 3-axis accel + 3-axis gyro (gaming)
Definition: sensor_fusion.h:69
struct ControlSubsystem * pControlSubsystem
quaternion structure definition
Definition: orientation.h:37
void ApplyPerturbation(SensorFusionGlobals *sfg)
The ApplyPerturbation function applies a user-specified step function to prior fusion results which i...
Definition: debug.c:53
The sensor_fusion.h file implements the top level programming interface.
#define F180OVERPI
radians to degrees conversion = 180 / pi
Quaternion derived from 3-axis accel (tilt)
Definition: sensor_fusion.h:65
Defines control sub-system.
SensorFusionGlobals sfg
This is the primary sensor fusion data structure.
float q2
y vector component
Definition: orientation.h:41
void qAeqAxB(Quaternion *pqA, const Quaternion *pqB)
function compute the quaternion product qA = qA * qB
Definition: orientation.c:969
float q1
x vector component
Definition: orientation.h:40
volatile uint8_t iPerturbation
test perturbation to be applied
volatile quaternion_type QuaternionPacketType
quaternion type transmitted over UART
Definition: control.h:66